#include "parse_cfg.h"
#include <yaml.h>
#include <unistd.h>

static int yaml_config_handler(void *data, yaml_parser_t *parser, yaml_event_t *event)
{
	dev_cfg_t *config = (dev_cfg_t *)data;

	switch (event->type)
	{
	case YAML_SCALAR_EVENT:
		// 解析标量值
		if (strcmp((char *)event->data.scalar.value, "log_dir") == 0)
		{
			yaml_event_t next_event;
			yaml_parser_parse(parser, &next_event);
			strncpy(config->log.log_dir, (char *)next_event.data.scalar.value, sizeof(config->log.log_dir));
			yaml_event_delete(&next_event);
		}
		else if (strcmp((char *)event->data.scalar.value, "max_files") == 0)
		{
			yaml_event_t next_event;
			yaml_parser_parse(parser, &next_event);
			config->log.max_files = atoi((char *)next_event.data.scalar.value);
			yaml_event_delete(&next_event);
		}
		else if (strcmp((char *)event->data.scalar.value, "addr") == 0)
		{
			yaml_event_t next_event;
			yaml_parser_parse(parser, &next_event);
			strncpy(config->mqtt.addr, (char *)next_event.data.scalar.value, sizeof(config->mqtt.addr));
			yaml_event_delete(&next_event);
		}
		else if (strcmp((char *)event->data.scalar.value, "whois") == 0)
		{
			yaml_event_t next_event;
			yaml_parser_parse(parser, &next_event);
			strncpy(config->mqtt.whois, (char *)next_event.data.scalar.value, sizeof(config->mqtt.whois));
			yaml_event_delete(&next_event);
		}
		else if (strcmp((char *)event->data.scalar.value, "sub") == 0)
		{
			yaml_event_t next_event;
			yaml_parser_parse(parser, &next_event);
			if (next_event.type == YAML_SEQUENCE_START_EVENT)
			{
				yaml_event_delete(&next_event);
				size_t sub_count = 0;
				while (1)
				{
					yaml_parser_parse(parser, &next_event);
					if (next_event.type == YAML_SCALAR_EVENT && sub_count < 10)
					{
						strncpy(config->mqtt.sub[sub_count], (char *)next_event.data.scalar.value, sizeof(config->mqtt.sub[sub_count]));
						sub_count++;
					}
					else if (next_event.type == YAML_SEQUENCE_END_EVENT)
					{
						yaml_event_delete(&next_event);
						config->mqtt.sub_count = sub_count;
						break;
					}
				}
			}
		}
		else if (strcmp((char *)event->data.scalar.value, "mb_ip") == 0)
		{
			yaml_event_t next_event;
			yaml_parser_parse(parser, &next_event);
			strncpy(config->modbus.mb_ip, (char *)next_event.data.scalar.value, sizeof(config->modbus.mb_ip));
			yaml_event_delete(&next_event);
		}
		else if (strcmp((char *)event->data.scalar.value, "mb_port") == 0)
		{
			yaml_event_t next_event;
			yaml_parser_parse(parser, &next_event);
			config->modbus.mb_port = atoi((char *)next_event.data.scalar.value);
			yaml_event_delete(&next_event);
		}
		else if (strcmp((char *)event->data.scalar.value, "fb_wait") == 0)
		{
			yaml_event_t next_event;
			yaml_parser_parse(parser, &next_event);
			config->ctrl.fb_wait = atoi((char *)next_event.data.scalar.value);
			yaml_event_delete(&next_event);
		}
		else if (strcmp((char *)event->data.scalar.value, "oil_wait") == 0)
		{
			yaml_event_t next_event;
			yaml_parser_parse(parser, &next_event);
			config->ctrl.oil_wait = atoi((char *)next_event.data.scalar.value);
			yaml_event_delete(&next_event);
		}
		else if (strcmp((char *)event->data.scalar.value, "main_wait") == 0)
		{
			yaml_event_t next_event;
			yaml_parser_parse(parser, &next_event);
			config->ctrl.main_wait = atoi((char *)next_event.data.scalar.value);
			yaml_event_delete(&next_event);
		}
		break;
	default:
		break;
	}
	return 1;
}

int yaml_parse(char *file, dev_cfg_t *cfg)
{
	if (access(file, F_OK) != 0)
	{
		printf("YAML File does not exist.\n");
		exit(0);
	}

	yaml_parser_t parser;
	yaml_parser_initialize(&parser);
	FILE *fp = fopen(file, "r");
	if (!fp)
	{
		fprintf(stderr, "Failed to open the YAML file.\n");
		return 1;
	}

	yaml_parser_set_input_file(&parser, fp);
	yaml_event_t event;
	int type = 0;
	do
	{
		yaml_parser_parse(&parser, &event);
		if (!yaml_config_handler(cfg, &parser, &event))
		{
			fprintf(stderr, "Failed to parse YAML.\n");
			break;
		}
		type = event.type;
		yaml_event_delete(&event);
	} while (type != YAML_STREAM_END_EVENT);

	fclose(fp);
	yaml_parser_delete(&parser);
	return 0;
}
